/*
 * Copyright 2013 Walter Lütgenau.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package offset.nodes.client.dialog.navigation.view;

import java.util.Enumeration;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import offset.nodes.client.dialog.navigation.model.NodeSelectionListener;

/**
 *
 * @author Walter Lütgenau
 */
public class HeadingPanel extends AbstractCardPanel {

    DefaultMutableTreeNode current = null;
    NodeSelectionListener nodeSelectionListener;
    Object selectedUserObject;

    class Heading {

        Object userObject;
        String text;
        int level;

        public Heading(Object userObject, String text, int level) {
            this.userObject = userObject;
            this.text = text;
            this.level = level;
        }

        public String getText() {
            return text;
        }

        public int getLevel() {
            return level;
        }

        public Object getUserObject() {
            return userObject;
        }

        public String toString() {
            return getText();
        }
    }

    @Override
    public String getCardName() {
        return "headings";
    }

    /**
     * The tree selection listener used to notify the node selection listener
     */
    protected class TreeSelectionHandler implements TreeSelectionListener {

        public void valueChanged(TreeSelectionEvent e) {
            if (headingTree.getSelectionCount() != 1)
                return;

            TreePath path = headingTree.getSelectionPath();
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
            Heading heading = (Heading) node.getUserObject();

            if (nodeSelectionListener != null) {
                selectedUserObject = heading.getUserObject();
                nodeSelectionListener.nodeSelected(heading.getText());
            }
        }
    }

    /**
     * Creates new form HeadingPanel
     */
    public HeadingPanel() {
        initComponents();
        headingTree.setCellRenderer(new HeadingRenderer());
        current = (DefaultMutableTreeNode) headingTree.getModel().getRoot();
        current.setUserObject(new Heading(null, "", 0));
    }

    /**
     * Set a node selection listener
     *
     * @param nodeSelectionListener
     */
    public void setNodeSelectionListener(NodeSelectionListener nodeSelectionListener) {
        this.nodeSelectionListener = nodeSelectionListener;
        headingTree.addTreeSelectionListener(new TreeSelectionHandler());
    }

    /**
     * Start to add headings for a new page
     */
    public void start() {
        current = (DefaultMutableTreeNode) headingTree.getModel().getRoot();
        current.removeAllChildren();
    }

    /**
     * Finish to add headings for a new page
     */
    public void end() {
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) headingTree.getModel().getRoot();
        
        ((DefaultTreeModel) headingTree.getModel()).nodeStructureChanged(root);        
        expandNodes(root);
    }

    protected void expandNodes(TreeNode node) {
        for (Enumeration children = node.children(); children.hasMoreElements();) {
            DefaultMutableTreeNode dtm = (DefaultMutableTreeNode) children.nextElement();
            if (!dtm.isLeaf()) {
                TreePath tp = new TreePath(dtm.getPath());
                headingTree.expandPath(tp);
                
                expandNodes(dtm);

            }
        }
    }

    public Object getSelectedUserObject() {
        return selectedUserObject;
    }

    /**
     * Add a heading of the specified level to the tree.
     *
     * @param text the text of the heading
     * @param level the level of the heading
     */
    public void addHeading(Object userObject, String text, int level) {
        DefaultMutableTreeNode child = new DefaultMutableTreeNode(new Heading(userObject, text, level));

        Heading currentHeading = (Heading) current.getUserObject();
        while (currentHeading != null && currentHeading.getLevel() >= level && current.getParent() != null) {
            current = (DefaultMutableTreeNode) current.getParent();
            currentHeading = (Heading) current.getUserObject();
        }

        current.add(child);
        current = child;
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT
     * modify this code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        headingTree = new javax.swing.JTree();

        setLayout(new java.awt.BorderLayout());

        jScrollPane2.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        headingTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        headingTree.setRowHeight(0);
        jScrollPane2.setViewportView(headingTree);

        add(jScrollPane2, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTree headingTree;
    private javax.swing.JScrollPane jScrollPane2;
    // End of variables declaration//GEN-END:variables
}
